﻿#include "FbxLoader.h"
#include "fbxsdk.h"
#include "Common.h"
#include <glm/mat4x4.hpp>
#include <vector>
#include <string>

namespace DYResources
{
	void PrintAxisSystem(FbxAxisSystem axisSystem, FbxAxisSystem::ECoordSystem& eCoord, FbxAxisSystem::EUpVector& eUp);

	FbxLoader::FbxLoader() : mScene(nullptr), mFactor(1)
	{
		mFbxManager = FbxManager::Create();
		mFbxSettings = FbxIOSettings::Create(mFbxManager, IOSROOT);
	}

	FbxLoader::~FbxLoader()
	{
		mFbxMeshes.clear();
		mSkeletonNodes.clear();
		if (mScene != nullptr) mScene->Destroy();
		mFbxSettings->Destroy();
		mFbxManager->Destroy();
	}

	bool FbxLoader::IsSkinnedMesh()
	{
		return !mSkeletonNodes.empty();
	}

	// 导入场景
	bool FbxLoader::Import(const char* pFbxFile)
	{
		// 配置输入输出对象
		mFbxSettings->SetBoolProp(IMP_FBX_MATERIAL, true);
		mFbxManager->SetIOSettings(mFbxSettings);

		// 初始化导入器
		FbxImporter* lImporter = FbxImporter::Create(mFbxManager, "");
		bool lImportStatus = lImporter->Initialize(pFbxFile, -1, mFbxSettings);
		if (!lImportStatus)
		{
			lImporter->Destroy();
			printf("FbxImporter::Initialize error, %s \n", lImporter->GetStatus().GetErrorString());
			return false;
		}

		// 创建场景并导入
		mScene = FbxScene::Create(mFbxManager, "");
		lImportStatus = lImporter->Import(mScene);
		if (!lImportStatus)
		{
			lImporter->Destroy();
			printf("FbxImporter::Import error, %s \n", lImporter->GetStatus().GetErrorString());
			return false;
		}

		// 导入完成可以销毁
		lImporter->Destroy();

		// 转换为OpenGL坐标系
		FbxGlobalSettings& globalSettings = mScene->GetGlobalSettings();
		FbxAxisSystem axisSystem = globalSettings.GetAxisSystem();
		if (axisSystem != FbxAxisSystem::OpenGL)
		{
			FbxAxisSystem::OpenGL.ConvertScene(mScene);
		}
		FbxAxisSystem::OpenGL.DeepConvertScene(mScene);

		// 转换为m作为单位
		FbxSystemUnit systemUnit = globalSettings.GetSystemUnit();
		mFactor = (float)FbxSystemUnit::m.GetConversionFactorFrom(systemUnit);
		if (globalSettings.GetSystemUnit() != FbxSystemUnit::m)
		{
			FbxSystemUnit::m.ConvertScene(mScene);
		}

		FbxNode* rootNode = mScene->GetRootNode();
		RetrieveNode(rootNode);

		return true;
	}

	// 检索Node
	void FbxLoader::RetrieveNode(FbxNode* pNode)
	{
		const char* nodeName = pNode->GetName();
		int attrCount = pNode->GetNodeAttributeCount();
		for (int i = 0; i < attrCount; i++)
		{
			FbxNodeAttribute* attribute = pNode->GetNodeAttributeByIndex(i);
			FbxNodeAttribute::EType type = attribute->GetAttributeType();
			switch (type)
			{
			case fbxsdk::FbxNodeAttribute::eSkeleton:
				mSkeletonNodes.push_back(pNode);
				break;
			case fbxsdk::FbxNodeAttribute::eMesh:
				mFbxMeshes.push_back((FbxMesh*)attribute);
				break;
			default:
				break;
			}
		}

		// 深度优先遍历
		int numChildren = pNode->GetChildCount();
		for (int i = 0; i < numChildren; i++)
		{
			FbxNode* childNode = pNode->GetChild(i);
			RetrieveNode(childNode);
		}
	}

	void PrintAxisSystem(FbxAxisSystem axisSystem, FbxAxisSystem::ECoordSystem& eCoord, FbxAxisSystem::EUpVector& eUp)
	{
		eCoord = axisSystem.GetCoorSystem();
		switch (eCoord)
		{
		case FbxAxisSystem::eRightHanded:
			Print("FbxAxisSystem::eRightHanded \n");
			break;
		case FbxAxisSystem::eLeftHanded:
			Print("FbxAxisSystem::eLeftHanded \n");
			break;
		default:
			break;
		}

		int dir;
		eUp = axisSystem.GetUpVector(dir);
		switch (eUp)
		{
		case FbxAxisSystem::eXAxis:
			Print("FbxAxisSystem::eXAxis \n");
			break;
		case FbxAxisSystem::eYAxis:
			Print("FbxAxisSystem::eYAxis \n");
			break;
		case FbxAxisSystem::eZAxis:
			Print("FbxAxisSystem::eZAxis \n");
			break;
		default:
			break;
		}
	}
}